package com.alks.function.service.impl.boardServiceImpl;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.DateUtils;
import com.alks.common.utils.MinIoUtil;
import com.alks.common.utils.excelUtils.ExcelPoiUtils;
import com.alks.common.utils.excelUtils.ExcelUtils;
import com.alks.common.utils.stringUtils.ZStringUtils;
import com.alks.entity.data.entity.ExportPlanInfo;
import com.alks.entity.data.entity.PcBoard;
import com.alks.entity.data.entity.board.FinanceOtherCharges;
import com.alks.entity.data.entity.board.SysDictData;
import com.alks.entity.data.entity.dispatch.UserOemRelation;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.controller.finance.borad.ExportPlan;
import com.alks.function.mapper.SdUserMapper;
import com.alks.function.mapper.board.BoardMapper;
import com.alks.function.service.boardService.BoardService;
import com.github.pagehelper.PageInfo;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static org.reflections.Reflections.log;

/**
 * @author:hxl
 * @create: 2024-08-03 15:27
 * @Description:
 */
@Service
public class BoardServiceImpl implements BoardService {
    @Autowired
    MinIoUtil minIoUtil;
    @Autowired
    private BoardMapper boardMapper;

    @Override
    public ResponseInfo uploadBoardFile(MultipartFile file, String invoiceNo) {
        String filename = "board/" + file.getOriginalFilename();
        minIoUtil.upload(file, "excel", filename);
        PcBoard pcBoard = new PcBoard();
        pcBoard.setCompanyId(UserIdThread.get().getCompanyId());
        pcBoard.setFileName(file.getOriginalFilename());
        pcBoard.setFilePath(filename);
        pcBoard.setInvoiceNo(invoiceNo);
        pcBoard.setSysTime(new Date());
        pcBoard.setSysUser(UserIdThread.get().getUserName());
        boardMapper.insert(pcBoard);
        //添加进数据库
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo deleteBoardFile(PcBoard pcBoard) {
        minIoUtil.removeObject("excel", pcBoard.getFilePath());
        boardMapper.delete(pcBoard);
        return ResponseInfo.ok();
    }

    @Override
    @AutoPageAop
    public ResponseInfo queryBoard(ExportPlan exportPlan) {
        exportPlan.setCompanyId(UserIdThread.get().getCompanyId());
        Map<String, Object> map = new HashMap<>();
        List<ExportPlan> list = boardMapper.selectExportPlanList(exportPlan);
        map.put("list", list);
        map.put("total", new PageInfo(list).getTotal());
        Map<String, Object> summaryRoot = boardMapper.sumStorage(exportPlan);
        Map<String, Object> result = boardMapper.sumStorage2(exportPlan);
        summaryRoot.put("arAmt", result.get("arAmt"));
        summaryRoot.put("additionalCost", result.get("additionalCost"));
        map.put("summaryRoot", summaryRoot);
        return ResponseInfo.ok(map);
    }

    @Override
    @AutoPageAop
    public ResponseInfo queryBoardDetail(ExportPlanInfo exportPlanInfo) {
        Map<String, Object> map = new HashMap<>();
        List<ExportPlanInfo> list = boardMapper.selectExportPlanInfoList(exportPlanInfo);
        map.put("list", list);
        map.put("total", new PageInfo(list).getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    @Transactional
    public ResponseInfo editBoardDetail(ExportPlanInfo exportPlanInfo) {
        ExportPlan exportPlan = new ExportPlan();
        exportPlan.setCompanyId(exportPlanInfo.getCompanyId());
        exportPlan.setFactoryLotNo(exportPlanInfo.getFactoryLotNo());
        exportPlan.setInvoiceNo(exportPlanInfo.getInvoiceNo());
        List<ExportPlan> list = boardMapper.selectExportPlanList(exportPlan);
        ExportPlan reExport = list.get(0);
        if ("Y".equals(reExport.getCfmFlag())) {
            throw new ServiceErrorException("该发票号已检核，请检查！");
        }
        int count = boardMapper.queryNumbyCollectDetail(exportPlanInfo);
        int updataRow = 0;
        if (count > 0) {
            updataRow = boardMapper.updateExportPlanInfo(exportPlanInfo);
        } else {
            int oemCount = boardMapper.queryNumbyOemOutDetail(exportPlanInfo);
            if (oemCount > 0) {
                updataRow = boardMapper.updateAddOEMPrice(exportPlanInfo);
            }
        }
        return ResponseInfo.ok(updataRow);
    }

    @Override
    @Transactional
    public ResponseInfo editBoardSaveData(List<ExportPlan> details) {
        if (details != null && details.size() != 0) {
            ExportPlan head = (ExportPlan) details.get(0);
            if (head.getExportType() == null) {
                throw new ServiceErrorException("出口类型不能为空!");
            } else {
                head.setSysUser(UserIdThread.get().getUserName());
                head.setSysDate(new Date());
                BigDecimal totallMoney = new BigDecimal(0.0);
                double outAmt = head.getOutAmt() == null ? 0.0 : head.getOutAmt();
                Calendar mon = Calendar.getInstance();
                Iterator var7 = details.iterator();
                ExportPlan exportPlan;
                while (var7.hasNext()) {
                    exportPlan = (ExportPlan) var7.next();
                    double arAmt = exportPlan.getArAmt() == null ? 0.0 : exportPlan.getArAmt();
                    BigDecimal num1 = new BigDecimal(arAmt);
                    totallMoney = totallMoney.add(num1);
                    exportPlan.setDetailUid(UUID.randomUUID().toString());
                    if (exportPlan.getPayDays() != null) {
                        if (head.getShipDate() == null) {
                            throw new ServiceErrorException("存在账期则船期不能为空!");
                        }

                        mon.setTime(head.getShipDate());
                        mon.add(5, exportPlan.getPayDays());
                        exportPlan.setArDate(mon.getTime());
                    }
                }
                if (outAmt < totallMoney.setScale(2, 4).doubleValue()) {
                    throw new ServiceErrorException("收款金额不能大于出货金额!");
                } else {
                    int result = 0;
                    exportPlan = boardMapper.selectExportPlanHeadById(head);
                    if (exportPlan != null && !ZStringUtils.isEmpty(exportPlan.getHeadUid())) {
                        head.setHeadUid(exportPlan.getHeadUid());
                    }

                    if (head.getHeadUid() == null) {
                        head.setHeadUid(UUID.randomUUID().toString());
                        result += boardMapper.insertBoardHead(head);
                    } else {
                        result += boardMapper.updateExportPlanHead(head);
                    }

                    boardMapper.deleteByRinvoiceNo((ExportPlan) details.get(0));
                    result += boardMapper.insertBatch(details);
                    return ResponseInfo.ok(result);
                }
            }
        }
        throw new ServiceErrorException("至少添加一笔收款类型!");
    }

    @Override
    @Transactional
    public ResponseInfo updateCfmFlag(String detailUid, String invoiceNo, String cfmFlag) {
        if (detailUid == null) {
            throw new ServiceErrorException("请先确认收款数据!");
        } else {
            ExportPlan param = ExportPlan.builder().cfmFlag(cfmFlag).cfmTime((Date) null).cfmUser((String) null).detailUid(detailUid).invoiceNo(invoiceNo).build();
            if ("Y".equals(cfmFlag)) {
                ExportPlan exportPlan = boardMapper.queryArAmtByInvoiceNo(UserIdThread.get().getCompanyId(), invoiceNo);
                double outAmt = exportPlan.getOutAmt() == null ? 0.0 : exportPlan.getOutAmt();
                double arAmt = exportPlan.getArAmt() == null ? 0.0 : exportPlan.getArAmt();
                if (outAmt != arAmt && !"其他".equals(exportPlan.getOrderType())) {
                    throw new ServiceErrorException("应收金额不等出货金额!!!");
                }
                param.setCfmTime(new Date());
                param.setCfmUser(UserIdThread.get().getLoginName());
            } else {
                int recAmt = boardMapper.queryRecAmtByInvoiceNo(UserIdThread.get().getCompanyId(), invoiceNo);
                if (recAmt > 0) {
                    throw new ServiceErrorException("已有实收金额[" + recAmt + "]不能取消审核!!!");
                }
            }
            boardMapper.updateCfmFlag(param);
            return ResponseInfo.ok();
        }
    }

    @Override
    @Transactional
    public ResponseInfo otherSaveData(List<ExportPlan> details) {
        if (details != null && details.size() != 0) {
            ExportPlan head = (ExportPlan) details.get(0);
            head.setSysUser(UserIdThread.get().getLoginName());
            head.setSysDate(new Date());
            Calendar mon = Calendar.getInstance();

            ExportPlan item;
            for (Iterator var4 = details.iterator(); var4.hasNext(); item.setCompanyId(UserIdThread.get().getCompanyId())) {
                item = (ExportPlan) var4.next();
                item.setDetailUid(UUID.randomUUID().toString());
                if (item.getPayDays() != null) {
                    mon.setTime(head.getShipDate());
                    mon.add(5, item.getPayDays());
                    item.setArDate(mon.getTime());
                }
            }
            int result = 0;
            if (head.getHeadUid() == null) {
                head.setHeadUid(UUID.randomUUID().toString());
                boardMapper.insertOther(head);
                result += boardMapper.insertBoardHead(head);
            } else {
                result += boardMapper.updateExportPlanHead(head);
            }
            boardMapper.deleteByRinvoiceNo((ExportPlan) details.get(0));
            result += boardMapper.insertBatch(details);
            return ResponseInfo.ok(result);
        } else {
            throw new ServiceErrorException("至少添加一笔收款类型!");
        }
    }

    @Override
    @Transactional
    public ResponseInfo deleteDetail(ExportPlan exportPlan) {
        boardMapper.insertIntoLog(exportPlan,UserIdThread.get().getUserName());
        boardMapper.deleteOtherByInvNo(exportPlan);
        boardMapper.deleteByRowId(exportPlan);
        boardMapper.deleteByRinvoiceNo(exportPlan);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo updateCreditNo(String creditNo, Date deliveryDate, List<ExportPlan> records,Date shipDate) {
        if (shipDate!=null){
            records.forEach(x->x.setShipDate(shipDate));
            boardMapper.updateShipDate(records);
        }
        Iterator var4 = records.iterator();
        while (var4.hasNext()) {
            ExportPlan item = (ExportPlan) var4.next();
            item.setCreditNo(creditNo);
            item.setDeliveryDate(deliveryDate);
        }
        boardMapper.updateCreditNo(records);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo annexList(String invoiceNo) {
        List<PcBoard> list = boardMapper.listObjects(invoiceNo, UserIdThread.get().getCompanyId());
        return ResponseInfo.ok(list);
    }

    @Override
    public void downloadBoard(HttpServletResponse response, ExportPlan exportPlan) throws IOException {
        exportPlan.setCompanyId(UserIdThread.get().getCompanyId());
        List<ExportPlan> list = boardMapper.selectExportPlanList(exportPlan);
        exportPlan.setCompanyId(UserIdThread.get().getCompanyId());
        ExcelUtils.creatByTemplate(response, "船务作业导出模板.xlsx", "船务作业导出-" + DateUtils.dateTimeNow(), list);
    }

    @Override
    @AutoPageAop
    public ResponseInfo loadInSumList(FinanceOtherCharges financeOtherCharges) {
        financeOtherCharges.setCompanyId(UserIdThread.get().getCompanyId());
        if ("1".equals(financeOtherCharges.getIsMines())) {
            financeOtherCharges.setCreateUser(UserIdThread.get().getLoginName());
        }
        Map<String, Object> map = new HashMap<>();
        List<FinanceOtherCharges> list = boardMapper.loadInSumList(financeOtherCharges);
        Map<String, Object> summaryRoot = boardMapper.sumOtherStorage(financeOtherCharges);
        map.put("summaryRoot", summaryRoot);
        map.put("total", new PageInfo(list).getTotal());
        map.put("list", list);
        return ResponseInfo.ok(map);
    }

    @Override
    @Transactional
    public ResponseInfo deleteOtherDetail(List<FinanceOtherCharges> financeOtherCharges) {
        boardMapper.deleteOtherDetail(financeOtherCharges, UserIdThread.get().getCompanyId());
        return ResponseInfo.ok();
    }

    @Override
    @Transactional
    public ResponseInfo addOtherCharges(List<FinanceOtherCharges> financeOtherCharges) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        String date = sdf.format(new Date());
        String companyId = UserIdThread.get().getCompanyId();
        Integer maxReceiptNo = boardMapper.selectMaxChargesNo(companyId);
        Iterator var6 = financeOtherCharges.iterator();
        while (var6.hasNext()) {
            FinanceOtherCharges item = (FinanceOtherCharges) var6.next();
            item.setChargesNo("FY" + date + String.format("%04d", maxReceiptNo));
            item.setCreateUser(UserIdThread.get().getLoginName());
            item.setCreateDate(new Date());
            item.setCompanyId(companyId);
        }
        boardMapper.addOtherCharges(financeOtherCharges);
        return ResponseInfo.ok();
    }

    @Override
    @Transactional
    public ResponseInfo updateDutyAmount(FinanceOtherCharges financeOtherCharges) {
        boardMapper.updateDutyAmount(financeOtherCharges);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo updateOtherCfmFlag(FinanceOtherCharges param) {
        param.setCompanyId(UserIdThread.get().getCompanyId());
        param.setCfmUser((String) null);
        param.setCfmDate((Date) null);
        if ("Y".equals(param.getCfmFlag())) {
            param.setCfmDate(new Date());
            param.setCfmUser(UserIdThread.get().getLoginName());
        }
        boardMapper.updateOtherCfmFlag(param);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo updateAoaMonth(List<FinanceOtherCharges> records, Date aoaMonth) {
        Iterator var3 = records.iterator();
        while (var3.hasNext()) {
            FinanceOtherCharges item = (FinanceOtherCharges) var3.next();
            item.setAoaMonth(aoaMonth);
        }
        boardMapper.updateAoaMonth(records);
        return ResponseInfo.ok();
    }

    @Autowired
    SdUserMapper sdUserMapper;
    @Override
    @Transactional
    public ResponseInfo importOtherCharges(MultipartFile file) {
        Map<String, Object> data = new HashMap<>();
        String fileName = file.getOriginalFilename().toLowerCase();
        if (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")) {
            data.put("success", Boolean.valueOf(false));
            data.put("msg", "请上传Excel文件");
            throw new ServiceErrorException((String) data.get("msg"));
        }
        List<FinanceOtherCharges> charges = excelInput(file);
        try {
            if (charges.size() == 0) {
                data.put("success", Boolean.valueOf(false));
                data.put("msg", "未找到需要导入任何记录");
                throw new ServiceErrorException((String) data.get("msg"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            data.put("success", Boolean.valueOf(false));
            data.put("msg", "解析excel文件出错:" + e.getMessage());
            throw new ServiceErrorException((String) data.get("msg"));
        }
        List<FinanceOtherCharges> combolist = boardMapper.custInvNoCombo(UserIdThread.get().getCompanyId(),(String)null);
        SysDictData dictData = new SysDictData();
        dictData.setDictType("other_charges_type");
        dictData.setStatus("0");
        List<SysDictData> dictDataList = boardMapper.selectDictDataList(dictData);
        Integer id = sdUserMapper.getUserIdByName(UserIdThread.get().getUserName());
        List<UserOemRelation> userOemRelations = boardMapper.selectUserOemRelationList(UserIdThread.get().getCompanyId(),id);
        Iterator var10 = charges.iterator();
        while(var10.hasNext()) {
            FinanceOtherCharges foc = (FinanceOtherCharges)var10.next();
            List filtList;
            if (ZStringUtils.isNotEmpty(foc.getDutyFactory())) {
                filtList = (List)userOemRelations.stream().filter((userOemRelation) -> foc.getDutyFactory().equals(userOemRelation.getVendorAbbr())).collect(Collectors.toList());
                if (filtList.size() == 0) {
                    return ResponseInfo.error("未查到相关责任工厂，请检查！");
                }
            }

            if (ZStringUtils.isNotEmpty(foc.getChargesType())) {
                filtList = (List)dictDataList.stream().filter((sysDictData) -> foc.getChargesType().equals(sysDictData.getDictValue())).collect(Collectors.toList());
                if (filtList.size() == 0) {
                    return ResponseInfo.error("未查到相关费用类型，请检查！");
                }
            }

            if (ZStringUtils.isNotEmpty(foc.getSupplierName())) {
                filtList = this.boardMapper.searchAll(UserIdThread.get().getCompanyId(),foc.getSupplierName());
                if (filtList.size() == 0) {
                    return ResponseInfo.error("未查到相关供应商，请检查！");
                }
            }

            if (ZStringUtils.isNotEmpty(foc.getCustInvNo())) {
                filtList = (List)combolist.stream().filter((financeOC) -> {
                    if (!foc.getCustInvNo().equals(financeOC.getCustInvNo())) {
                        return false;
                    } else {
                        foc.setOutNum(financeOC.getOutNum());
                        foc.setFactoryName(financeOC.getFactoryName());
                        return true;
                    }
                }).collect(Collectors.toList());
                if (filtList.size() == 0) {
                    return ResponseInfo.error("未查到相关客人发票号，请检查！");
                }
            }
        }

        this.addOtherCharges(charges);
        return ResponseInfo.ok("导入成功");
    }

    @Override
    public void downloadOtherCharges(HttpServletResponse response, FinanceOtherCharges financeOtherCharges) throws IOException {
        financeOtherCharges.setCompanyId(UserIdThread.get().getCompanyId());
        if (financeOtherCharges.isMine()) {
            financeOtherCharges.setCreateUser(UserIdThread.get().getUserName());
        }
        List<FinanceOtherCharges> list = boardMapper.loadInSumList(financeOtherCharges);
        ExcelUtils.creatByTemplate(response, "其他费用导出模板.xls", "其他费用导出-"+DateUtils.dateTimeNow(), list);
    }

    private List<FinanceOtherCharges> excelInput(MultipartFile file) {
        String excelFileName = file.getOriginalFilename();
        int excelVersion = ExcelPoiUtils.getExcelVersion(excelFileName);
        Workbook workbook = null;
        List<FinanceOtherCharges> list = null;

        // 2003版本xls
        if (excelVersion == 1) {
            try {
                log.info("导入文件名:{},文件版本:2003", excelFileName);
                workbook = new HSSFWorkbook(file.getInputStream());
                list = readExcelValue1(workbook);
                return list;
            } catch (IOException e) {
                log.error("文件导入失败!");
                e.printStackTrace();
            }
        }
        // 2007版本xlsx
        if (excelVersion == 2) {
            try {
                log.info("导入文件名:{},文件版本:2007", excelFileName);
                workbook = new XSSFWorkbook(file.getInputStream());
                list = readExcelValue1(workbook);
                return list;
            } catch (IOException e) {
                log.error("文件导入失败!");
                e.printStackTrace();
            }
        }
        return null;
    }

    private List<FinanceOtherCharges> readExcelValue1(Workbook workbook) {
        int totalRows = 0;
        int totalCells = 0;
        Sheet sheet = workbook.getSheetAt(0);
        // 得到表的总行数
        totalRows = sheet.getPhysicalNumberOfRows();
        // 根据第一行（标题行）获得总列数，获得总列数得根据某行确定
        if (totalRows >= 1 && sheet.getRow(0) != null) {
            totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
        }
        List<FinanceOtherCharges> list = new ArrayList<>();
        for (int rowNum = 1; rowNum < totalRows; rowNum++) {
            // 跳过标题行
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                continue;
            }
            FinanceOtherCharges vo = new FinanceOtherCharges();
            for (int colNum = 0; colNum < totalCells; colNum++) {
                Cell cell = row.getCell(colNum);
                if (null != cell) {
                    switch (cell.getCellType()) {
                        case NUMERIC:
                            switch (colNum) {
                                case 3:
                                    vo.setAmount(cell.getNumericCellValue());
                                    break;
                                case 5:
                                    vo.setDutyAmount(cell.getNumericCellValue());
                                    break;
                            }
                            break;
                        case STRING:
                            switch (colNum) {
                                case 0:
                                    vo.setCustInvNo(cell.getStringCellValue());
                                    break;
                                case 1:
                                    vo.setSupplierName(cell.getStringCellValue());
                                    break;
                                case 2:
                                    vo.setChargesType(cell.getStringCellValue());
                                    break;
                                case 4:
                                    vo.setDutyFactory(cell.getStringCellValue());
                                    break;
                                case 6:
                                    vo.setRemark(cell.getStringCellValue());
                                    break;
                            }
                            break;
                    }
                }
            }
            list.add(vo);
        }
        return list;
    }
}